package il.technion.cs236369.proxy;

import java.io.FileInputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Properties;

import javax.net.ServerSocketFactory;
import javax.net.SocketFactory;

import org.apache.http.impl.DefaultHttpServerConnection;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.CoreProtocolPNames;

import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.name.Named;

public class HttpProxy extends AbstractHttpProxy {

	private BasicHttpParams params;
	private ServerSocket serverSocket;

	@Inject
	HttpProxy(SocketFactory sockFactory, ServerSocketFactory srvSockFactory,

	@Named("httproxy.net.port") int port,
			@Named("httproxy.db.url") String dbURL,
			@Named("httproxy.db.name") String dbName,
			@Named("httproxy.db.table") String tblName,
			@Named("httproxy.db.username") String dbUsername,
			@Named("httproxy.db.password") String dbPassword,
			@Named("httproxy.db.driver") String dbDriver)
			throws ClassNotFoundException {
		super(sockFactory, srvSockFactory, port, dbURL, dbName, tblName,
				dbUsername, dbPassword, dbDriver);
		// Add your code here
		//set proprties?!!
		this.params = new BasicHttpParams();
        this.params
            .setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 5000)
            .setIntParameter(CoreConnectionPNames.SOCKET_BUFFER_SIZE, 10 * 1024)
            .setBooleanParameter(CoreConnectionPNames.STALE_CONNECTION_CHECK, false)
            .setBooleanParameter(CoreConnectionPNames.TCP_NODELAY, true)
            .setParameter(CoreProtocolPNames.ORIGIN_SERVER, "HttpComponents/1.1");
	}
	

	@Override
	public void bind() throws IOException {
		// Create server socket listening on given port
		this.serverSocket = srvSockFactory.createServerSocket(port);
		
		
		}

	@Override
	public void start() {
		System.out.println("Proxy is running");
		while(true) {
			Socket insocket = null;
			DefaultHttpServerConnection inconn = null;
			try {
				try {
					System.out.println("Accepting connection...");
					insocket = this.serverSocket.accept();
				} catch (IOException e1) {
					System.err.println("Unable to accept incoming socket");
					continue;
				}
				inconn = new DefaultHttpServerConnection();
				System.out.println("Incoming connection from " + insocket.getInetAddress());
				try {
					inconn.bind(insocket, this.params);
				} catch (IOException e1) {
					System.err.println("Unable to bind incoming socket, closing the socket...");
					if (insocket != null) {
						try {
							insocket.close();
						} catch (IOException e) {
							System.err.println("Unable to close incoming socket");
						}
					}
					continue;
				}
			} finally {
//				try {
//					if (insocket != null) {
//						insocket.close();
//					}
//				} catch (IOException e) {
//					System.err.println("Unable to close incoming socket");
//				}
				try {
					if (inconn != null) {
						inconn.close();
					}
				} catch (IOException e) {
					System.err.println("Unable to close incoming connection");
				}
			//	handler.closeConnections();
			}
		}
	}
	
	
	
	public static void logp(String s) {
		     System.out.println(s);
		  }

	public static void main(String[] args) throws Exception {
		Properties p = new Properties();
		p.load(new FileInputStream("config"));
		Injector inj = Guice.createInjector(new HttpProxyModule(p));
		// Injector inj = Guice.createInjector(new HttpProxyModule());
		IHttpProxy proxy = inj.getInstance(HttpProxy.class);
		proxy.bind();
		proxy.start();

	}
}
